#include "PropertiesBox.h"
#include "CommCtrl.h"
#include "Button.h"
#include <windowsx.h>
#include "CheckBox.h"

PropertiesBox::PropertiesBox()
: m_rowCount(0)
, m_colCount(0)
, m_hWnd(NULL)
{
}
PropertiesBox::~PropertiesBox()
{
	DeleteAll();
}
bool PropertiesBox::Setup(HWND a_hWnd, HINSTANCE a_hInst, int a_xPos, int a_yPos, int a_width, int a_height)
{
	//Hold onto the parent window (propertieswindow) to use for setting the buttons parent
	m_hParentWnd = a_hWnd;
	m_hWnd = CreateWindowEx(NULL, WC_LISTVIEW, "", WS_VISIBLE | WS_CHILD | LVS_SORTASCENDING | LVS_REPORT | WS_BORDER | LVS_EDITLABELS | LVS_SHOWSELALWAYS | WS_CLIPSIBLINGS, a_xPos, a_yPos, a_width, a_height, a_hWnd, NULL, a_hInst, (LPVOID)this);
	if(m_hWnd == NULL)
	{
		return false;
	}

	ListView_SetExtendedListViewStyle(m_hWnd, LVS_EX_GRIDLINES | LVS_EX_DOUBLEBUFFER);
	ListView_EnableGroupView(m_hWnd, true);

	SetupImages();
	UpdateWindow(m_hWnd);
	ShowWindow(m_hWnd, SW_SHOW);

	//Create a nameless group for users to use if they do not want a group
	AddGroup("", -1);

	return true;
}

bool PropertiesBox::SetupImages()
{
	LVBKIMAGE lvb;
	lvb.ulFlags = LVBKIF_SOURCE_URL | LVBKIF_STYLE_TILE;
	lvb.pszImage = "media/Textures/lightbulb.png";
	OleInitialize(NULL);
	SendMessage(m_hWnd, LVM_SETBKIMAGE, 0, (LPARAM)&lvb);

	/*HICON hIcon;
	HIMAGELIST hLarge;
	HIMAGELIST hSmall;

	HINSTANCE hLib = LoadLibrary("shell32.dll");

	hLarge = ImageList_Create(GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), ILC_MASK, 1, 1);

	hSmall = ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), ILC_MASK, 1, 1);

	hIcon = LoadIcon(hLib, MAKEINTRESOURCE(3));
	ImageList_AddIcon(hLarge, hIcon);
	ImageList_AddIcon(hSmall, hIcon);

	DestroyIcon(hIcon);
	FreeLibrary(hLib);

	ListView_SetImageList(m_hWnd, hLarge, LVSIL_NORMAL);
	ListView_SetImageList(m_hWnd, hSmall, LVSIL_SMALL);*/

	return true;
}
void PropertiesBox::Sort()
{
	//ListView_SortItems(m_hWnd, , 0);
}
bool PropertiesBox::DeleteColumn(int a_index)
{
	return SendMessage(m_hWnd, LVM_DELETECOLUMN, (WPARAM)a_index, 0);
}
bool PropertiesBox::DeleteRow(int a_index)
{
	return SendMessage(m_hWnd, LVM_DELETEITEM, (WPARAM)a_index, 0);
}
bool PropertiesBox::DeleteAll()
{
	for(UINT i=0, size = m_buttons.size(); i<size; ++i)
	{
		delete m_buttons[i].second;
		m_buttons[i].second = NULL;
	}
	m_buttons.clear();
	return SendMessage(m_hWnd, LVM_DELETEALLITEMS, 0, 0);
}
void PropertiesBox::AddColumn(int a_width, const char* a_pLabel)
{
	LVCOLUMN lvc;
	ZeroMemory(&lvc, sizeof(LVCOLUMN));

	lvc.mask = LVCF_TEXT | LVCF_FMT | LVCF_WIDTH | LVCF_SUBITEM | LVCF_IMAGE;
	//left aligned
	lvc.fmt  = LVCFMT_LEFT;

	//Add cols
	lvc.iSubItem = 0;
	//col width
	lvc.cx = a_width;
	//lvc.iImage = -1;
	char buffer[256];
	sprintf_s(buffer, 256, "%s", a_pLabel);
	lvc.pszText = buffer;
	ListView_InsertColumn(m_hWnd, m_colCount, &lvc);

	++m_colCount;
}
void PropertiesBox::AddRow(const char* a_pLabel, int a_groupID)
{
	//Add rows
	LVITEM lvi;
	ZeroMemory(&lvi, sizeof(LVITEM));

	lvi.mask = LVIF_TEXT | LVIF_GROUPID;
	char buffer[512];
	sprintf_s(buffer, 512, "%s", a_pLabel);
	lvi.pszText = buffer;
	lvi.iItem = m_rowCount;
	lvi.iGroupId = a_groupID;
	ListView_InsertItem(m_hWnd, &lvi);

	++m_rowCount;
}
void PropertiesBox::AddButton(char* a_pLabel, char* a_pTooltip, int a_rowIndex, int a_subItemIndex)
{
	RECT rect;
	LVITEMINDEX lvid;
	ZeroMemory(&lvid, sizeof(LVITEMINDEX));
	lvid.iItem = a_subItemIndex;

	rect.top = a_subItemIndex;
	rect.left = LVIR_LABEL;
	if(!SendMessage(m_hWnd, LVM_GETSUBITEMRECT, (WPARAM)a_rowIndex, (LPARAM)&rect))
	{
		return;
	}

	Button* pButton = new Button();
	pButton->Setup(m_hWnd, GetModuleHandle(NULL), rect.left, rect.top, 50, 18, a_pLabel, a_pTooltip);

	ButtonRowPair temp;
	temp.first = a_rowIndex;
	temp.second = pButton;
	m_buttons.push_back(temp);

	if(SetParent(pButton->GetHandle(), m_hParentWnd) == NULL)
	{
		return;
	}

}
void PropertiesBox::AddGroup(char* a_pLabel, int a_groupID)
{
	//Slight hack - the pszHeader needs a wchar_t, to make the input of the function more elegant,
	//it does a conversion here from char* to wchar_t and feeds it into the group header pszHeader.

	wchar_t newLabel[128];
	mbstowcs(newLabel, a_pLabel, 128);
	LVGROUP lvg;
	lvg.cbSize = sizeof(LVGROUP);
	lvg.mask = LVGF_HEADER | LVGF_GROUPID;
	lvg.pszHeader = newLabel;
	lvg.iGroupId = a_groupID;
	ListView_InsertGroup(m_hWnd, -1, &lvg);
}
COLORREF PropertiesBox::ColorShade(COLORREF a_cf, float a_percent)
{
	return RGB((BYTE)((float)GetRValue(a_cf) * a_percent / 100.0f), (BYTE)((float)GetGValue(a_cf) * a_percent / 100.0f), (BYTE)((float)GetBValue(a_cf) * a_percent / 100.0f));
}
void PropertiesBox::PaintAlternating(HWND a_hWnd)
{
	RECT rectUpdated, rectDest, rect;

	POINT pt;
	int numItems, firstItem;
	COLORREF cf;

	GetUpdateRect(a_hWnd, &rectUpdated, false);
	//CallWindowProc((FARPROC)PrevWndFunc, m_hWnd, WM_PAINT, 0, 0);
	SetRect(&rect, rectUpdated.left, 0, rectUpdated.right, 0);
	numItems = ListView_GetCountPerPage(a_hWnd);
	firstItem = ListView_GetTopIndex(a_hWnd);

	ListView_GetItemPosition(a_hWnd, firstItem, &pt);
	for(int i=firstItem; i<=firstItem+numItems; ++i)
	{
		rect.top = pt.y;
		ListView_GetItemPosition(a_hWnd, i+1, &pt);
		rect.bottom = pt.y;

		if(IntersectRect(&rectDest, &rectUpdated, &rect))
		{
			cf = (i%2) ? ColorShade(GetSysColor(COLOR_WINDOW), 95.0) : GetSysColor(COLOR_WINDOW);
			ListView_SetTextBkColor(a_hWnd, cf);
			InvalidateRect(a_hWnd, &rect, false);
			//CallWindowProc((FARPROC)PrevWndFunc, m_hWnd, WM_PAINT, 0, 0);
		}
	}
}
void PropertiesBox::EraseAlternatingBackground(HWND a_hWnd, HDC a_hdc)
{
	if(a_hWnd == NULL)
		return;

	RECT rect;
	POINT pt;
	int numItems, firstItem;
	HBRUSH brushCol1, brushCol2;

	brushCol1 = CreateSolidBrush(GetSysColor(COLOR_WINDOW));
	brushCol2 = CreateSolidBrush(ColorShade(GetSysColor(COLOR_WINDOW), 95.0));

	GetClientRect(a_hWnd, &rect);

	numItems = ListView_GetCountPerPage(a_hWnd);
	firstItem = ListView_GetTopIndex(a_hWnd);

	ListView_GetItemPosition(a_hWnd, firstItem, &pt);

	for(int i=firstItem; i<=firstItem+numItems; ++i)
	{
		rect.top = pt.y;
		ListView_GetItemPosition(a_hWnd, i+1, &pt);
		rect.bottom = pt.y;
		FillRect(a_hdc, &rect, (i % 2) ? brushCol2 : brushCol1);
	}

	DeleteObject(brushCol1);
	DeleteObject(brushCol2);
}
Button* PropertiesBox::GetButton(int a_rowIndex)
{
	for(UINT i=0, size = m_buttons.size(); i<size; ++i)
	{
		if(m_buttons[i].first == a_rowIndex)
		{
			return m_buttons[i].second;
		}
	}
	//Not found
	return NULL;
}
void PropertiesBox::SetItemText(int a_row, int a_col, char* a_pLabel)
{
	ListView_SetItemText(m_hWnd, a_row, a_col, a_pLabel);
}
